package db4;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class SimpleDB {

    private static final String DATA_DIR = "data";

    private static final String METADATA_FILE = "metadata.properties";
    // 元数据容器：内存中缓存表结构，key=表名，value=列定义字符串（如"id,INT,name,STRING"）
    private Properties metadata;
    // 表数据容器：内存中缓存表的所有数据，key=表名，value=行数据列表（每行用Map<列名,值>存储）
    private Map<String, List<Map<String, Object>>> storage;

    /**
     * 程序入口：初始化数据库并启动命令行交互
     */
    public static void main(String[] args) {
        SimpleDB db = new SimpleDB();
        db.init();
        db.commandLoop();
    }

    /**
     * 初始化方法：创建内存容器，加载磁盘上的元数据和表数据到内存
     * 流程：先加载表结构（元数据），再根据元数据加载对应的数据文件
     */
    private void init() {

        metadata = new Properties();

        storage = new HashMap<>();

        loadMetadata();
        loadStorage();
    }

    /**
     * 加载元数据：从磁盘文件读取表结构到内存metadata容器
     * 注意：首次运行时元数据文件不存在，容器为空，后续创建表时会自动生成文件
     */
    private void loadMetadata() {
        File metaFile = new File(METADATA_FILE);
        if (metaFile.exists()) {
            try (InputStream input = new FileInputStream(metaFile)) {
                metadata.load(input);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 保存元数据：将内存中的表结构写入磁盘文件（持久化）
     * 调用时机：创建表、修改表结构（ALTER）、删除表后，确保结构变更被保存
     */
    private void saveMetadata() {
        try (OutputStream output = new FileOutputStream(METADATA_FILE)) {
            metadata.store(output, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 加载表数据：根据元数据中的表名，从data目录读取对应.dat文件到内存storage容器
     * 核心逻辑：按表名匹配数据文件，逐行解析数据并转换为对应类型
     * 【修复点1】添加字段数校验，解决下标越界问题
     */
    private void loadStorage() {
        File dataDir = new File(DATA_DIR);
        if (!dataDir.exists()) {
            dataDir.mkdir();
        }

        // 遍历元数据中的所有表名（只加载已定义表结构的数据）
        for (String tableName : metadata.stringPropertyNames()) {
            // 为当前表初始化内存存储（空列表，后续添加解析后的行数据）
            storage.put(tableName, new ArrayList<>());
            // 数据文件路径：data/表名.dat（如data/student.dat）
            File tableFile = new File(dataDir, tableName + ".dat");

            // 仅当数据文件存在时才解析（表刚创建时可能还没有数据文件）
            if (tableFile.exists()) {
                try (Scanner scanner = new Scanner(tableFile)) {
                    // 逐行读取数据文件（每行对应一条记录）
                    while (scanner.hasNextLine()) {
                        String line = scanner.nextLine();
                        // 跳过空行（避免手动编辑文件时的空行导致解析错误）
                        if (line.trim().isEmpty()) continue;

                        // 按逗号分割字段值（注意：字符串值存储时带单引号，后续会处理）
                        String[] values = line.split(",");
                        // 存储当前行数据的Map（键为列名，值为转换后的数据类型）
                        Map<String, Object> row = new HashMap<>();
                        // 从元数据中获取当前表的列定义（如"id,INT,name,STRING"→分割为数组）
                        String[] columns = metadata.getProperty(tableName).split(",");

                        // 元数据columns数组长度是"列数×2"（每个列包含名称和类型），因此列数=长度/2
                        int expectedColCount = columns.length / 2;
                        if (values.length != expectedColCount) {
                            // 抛出自定义异常，明确提示错误原因（避免模糊的下标越界）
                            throw new RuntimeException(
                                    "表[" + tableName + "]数据格式错误：" +
                                            "预期" + expectedColCount + "个字段，实际" + values.length + "个字段（行内容：" + line + "）"
                            );
                        }

                        // 遍历列定义，匹配字段值（i每次+2，因为数组是[列名1,类型1,列名2,类型2,...]）
                        for (int i = 0; i < columns.length; i += 2) {
                            String columnName = columns[i];       // 当前列名（如"id"）
                            String columnType = columns[i + 1];  // 当前列类型（如"INT"）
                            // 处理字段值：移除字符串的首尾单引号（存储时添加的，读取时需要去掉）
                            String rawValue = values[i / 2].trim().replaceAll("^'|'$", "");
                            // 转换值为对应类型（INT→Integer，STRING→String），存入行Map
                            row.put(columnName, convertValue(rawValue, columnType));
                        }
                        // 将解析后的行数据添加到表的内存存储中
                        storage.get(tableName).add(row);
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 保存表数据：将内存中的表数据写入对应.dat文件（持久化）
     * 调用时机：插入、更新、删除数据后，确保数据变更被保存
     */
    private void saveStorage() {
        File dataDir = new File(DATA_DIR);
        // 遍历内存中所有表的数据集
        for (String tableName : storage.keySet()) {
            // 数据文件路径：data/表名.dat
            File tableFile = new File(dataDir, tableName + ".dat");
            try (PrintWriter writer = new PrintWriter(tableFile)) {
                // 遍历当前表的所有行数据
                for (Map<String, Object> row : storage.get(tableName)) {
                    List<String> values = new ArrayList<>();  // 存储格式化后的字段值
                    // 获取当前表的列定义（用于按顺序生成字段值）
                    String[] columns = metadata.getProperty(tableName).split(",");

                    // 按列定义顺序，格式化每个字段的值
                    for (int i = 0; i < columns.length; i += 2) {
                        String columnName = columns[i];       // 列名
                        Object value = row.get(columnName);   // 字段值（内存中的类型）
                        String columnType = columns[i + 1];   // 列类型
                        // 格式化值（INT直接转字符串，STRING加单引号避免逗号分割）
                        values.add(formatValue(value, columnType));
                    }
                    // 用逗号拼接所有字段值，写入文件（一行一条记录）
                    writer.println(String.join(",", values));
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 工具方法：将字符串值转换为列定义的类型（INT→Integer，其他→String）
     *
     * @param value 从数据文件读取的原始字符串值
     * @param type  列定义的类型（如"INT"或"STRING"）
     * @return 转换后的对象（Integer或String）
     */
    private Object convertValue(String value, String type) {
        if ("INT".equalsIgnoreCase(type)) {
            // 若类型为INT，尝试转换为Integer（值非法时抛异常，如"abc"不能转INT）
            try {
                return Integer.parseInt(value);
            } catch (NumberFormatException e) {
                throw new RuntimeException("INT类型字段值非法：" + value);
            }
        } else {
            // 非INT类型默认按String处理（直接返回原始值）
            return value;
        }
    }

    /**
     * 工具方法：将内存中的值格式化为适合写入文件的字符串
     *
     * @param value 内存中的值（Integer或String）
     * @param type  列定义的类型
     * @return 格式化后的字符串（INT无引号，STRING带单引号）
     */
    private String formatValue(Object value, String type) {
        if (value instanceof Integer && "INT".equalsIgnoreCase(type)) {
            // INT类型直接转字符串（如20→"20"）
            return value.toString();
        } else {
            // STRING类型加单引号（避免字段值包含逗号时被错误分割）
            // 同时将单引号转义为''（防止值中的单引号破坏格式）
            return "'" + value.toString().replace("'", "''") + "'";
        }
    }

    /**
     * 命令行交互循环：持续接收用户输入的SQL命令，解析并执行
     * 核心流程：读取命令→匹配类型→调用对应处理方法→捕获异常并提示
     */
    private void commandLoop() {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            // 打印命令提示符，等待用户输入
            System.out.print("SimpleDB> ");
            String sql = scanner.nextLine().trim();  // 读取并去除首尾空格

            // 若输入EXIT，退出循环（程序结束）
            if (sql.equalsIgnoreCase("EXIT")) {
                break;
            }

            // 捕获所有异常，避免程序崩溃，同时提示用户错误信息
            try {
                // 根据命令前缀匹配对应的处理方法
                if (sql.startsWith("CREATE TABLE")) {
                    createTable(sql);
                } else if (sql.startsWith("INSERT INTO")) {
                    insertData(sql);
                } else if (sql.startsWith("ALTER TABLE")) {
                    alterTable(sql);
                } else if (sql.startsWith("DELETE FROM")) {
                    deleteData(sql);
                } else if (sql.startsWith("UPDATE")) {
                    updateData(sql);
                } else if (sql.startsWith("DROP TABLE")) {
                    dropTable(sql);
                } else if (sql.startsWith("SELECT")) {
                    handleSelectQuery(sql);
                } else if (sql.equalsIgnoreCase("SHOW TABLES")) {
                    showAllTables();
                } else {
                    // 不支持的命令，提示用户
                    System.out.println("Unsupported command: " + sql);
                }
            } catch (Exception e) {
                // 打印异常信息（如语法错误、表不存在等）
                System.out.println("Error: " + e.getMessage());
            }
        }
        // 退出前保存所有变更（元数据和数据）
        saveChanges();
        scanner.close();  // 关闭输入流
    }

    /**
     * 保存所有变更：统一调用元数据和数据的保存方法
     * 调用时机：程序正常退出时，确保所有内存中的变更被持久化到磁盘
     */
    private void saveChanges() {
        saveMetadata();  // 保存表结构
        saveStorage();   // 保存表数据
    }

    /**
     * 显示所有表名（补充SHOW TABLES功能）
     * 语法示例：SHOW TABLES;
     */
    private void showAllTables() {
        System.out.println("=== All Tables ===");
        // 从元数据中获取所有表名（metadata的key就是表名）
        Set<String> tableNames = metadata.stringPropertyNames();
        if (tableNames.isEmpty()) {
            System.out.println("No tables in database.");
            return;
        }
        // 遍历并打印所有表名
        for (String table : tableNames) {
            System.out.println(table);
        }
    }

    // ======================== 查询处理功能实现 ========================

    /**
     * 处理SELECT查询命令：支持单表和多表的投影、选择、连接操作
     * 语法示例：
     * 1. SELECT 属性名列表 FROM 关系名
     * 2. SELECT * FROM 关系名 WHERE 条件表达式
     * 3. SELECT 属性名列表 FROM 关系名 WHERE 选择条件
     * 4. SELECT * FROM 关系名列表 WHERE 连接条件
     * 5. SELECT * FROM 关系名列表 WHERE 选择条件和连接条件
     * 6. SELECT 属性名列表 FROM 关系名列表 WHERE 连接条件
     * 7. SELECT 属性名列表 FROM 关系名列表 WHERE 条件表达式
     */
    private void handleSelectQuery(String sql) {
        if (sql.endsWith(";")) {
            sql = sql.substring(0, sql.length() - 1);
        }

        // 匹配SELECT查询的各种形式
        // 模式1: SELECT 属性列表 FROM 表列表 WHERE 条件
        Pattern pattern1 = Pattern.compile(
                "SELECT\\s+(.+?)\\s+FROM\\s+(.+?)(?:\\s+WHERE\\s+(.+?))?$",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher1 = pattern1.matcher(sql);

        if (matcher1.find()) {
            String attributes = matcher1.group(1).trim();     // 属性列表
            String tables = matcher1.group(2).trim();         // 表列表
            String conditions = matcher1.group(3);            // 条件（可能为null）

            // 解析表名列表  （如" student , score "→["student","score"]）
            String[] tableNames = tables.split(",");
            for (int i = 0; i < tableNames.length; i++) {
                tableNames[i] = tableNames[i].trim();
            }

            // 语义检查：表是否存在
            for (String tableName : tableNames) {
                if (!metadata.containsKey(tableName)) {
                    throw new IllegalArgumentException("Table not exists: " + tableName);
                }
            }

            // 根据查询类型调用不同的处理方法
            if (tableNames.length == 1) {
                // 单表查询
                handleSingleTableQuery(tableNames[0], attributes, conditions);
            } else {
                // 多表查询
                handleMultiTableQuery(tableNames, attributes, conditions);
            }
        } else {
            throw new IllegalArgumentException("Invalid SELECT syntax");
        }
    }

    /**
     * 处理单表查询
     *
     * @param tableName  表名
     * @param attributes 属性列表 (* 或具体属性名)
     * @param conditions 条件表达式 (可能为null)
     */
    private void handleSingleTableQuery(String tableName, String attributes, String conditions) {
        // 从内存缓存中获取当前表的所有数据（每行是Map<列名,值>）
        List<Map<String, Object>> tableData = storage.get(tableName);
        // 从元数据中获取表的列定义（格式："id,INT,name,STRING"→分割为数组）
        String[] columnDefs = metadata.getProperty(tableName).split(",");

        // 提取所有列名（列定义数组是[列名1,类型1,列名2,类型2...]，步长2取列名）
        List<String> allColumns = new ArrayList<>();
        for (int i = 0; i < columnDefs.length; i += 2) {
            allColumns.add(columnDefs[i]);
        }

        // 确定要投影的列（即最终要显示的列）
        List<String> projectionColumns;
        if (attributes.equals("*")) {
            // 如果是*，表示投影所有列
            projectionColumns = allColumns;
        } else {
            // 如果是指定列（如"id,name"），分割后处理
            projectionColumns = Arrays.asList(attributes.split(","));
            // 去除每个列名的空格（如" id , name "→["id","name"]）
            for (int i = 0; i < projectionColumns.size(); i++) {
                projectionColumns.set(i, projectionColumns.get(i).trim());
            }
            // 语义检查：确保投影的列都存在于表中（避免查询不存在的列）
            for (String col : projectionColumns) {
                if (!allColumns.contains(col)) {
                    throw new IllegalArgumentException("Column not exists: " + col);
                }
            }
        }

        // 处理选择条件（筛选符合条件的行）
        List<Map<String, Object>> resultData = new ArrayList<>();
        if (conditions == null) {
            // 无WHERE条件→选择所有行
            resultData.addAll(tableData);
        } else {
            // 有WHERE条件→调用filterRows筛选满足条件的行
            resultData = filterRows(tableData, conditions, tableName);
        }

        // 执行投影并显示结果（只显示projectionColumns指定的列）
        displayQueryResult(resultData, projectionColumns, tableName);
    }

    /**
     * 处理多表查询（连接操作）
     *
     * @param tableNames 表名列表
     * @param attributes 属性列表 (* 或具体属性名)
     * @param conditions 条件表达式 (可能为null)
     */
    private void handleMultiTableQuery(String[] tableNames, String attributes, String conditions) {
        // 获取所有表的数据
        List<List<Map<String, Object>>> allTableData = new ArrayList<>();
        Map<String, String[]> tableColumns = new HashMap<>();

        for (String tableName : tableNames) {
            allTableData.add(storage.get(tableName));
            String[] columnDefs = metadata.getProperty(tableName).split(",");
            tableColumns.put(tableName, columnDefs);
        }

        // 执行笛卡尔积
        List<Map<String, Object>> cartesianProduct = computeCartesianProduct(allTableData, tableNames);

        // 处理连接和选择条件
        List<Map<String, Object>> resultData = new ArrayList<>();
        if (conditions == null) {
            resultData.addAll(cartesianProduct);
        } else {
            resultData = filterJoinedRows(cartesianProduct, conditions, tableNames, tableColumns);
        }

        // 确定要投影的列
        List<String> projectionColumns;
        if (attributes.equals("*")) {
            // 获取所有列名（带表名前缀）
            projectionColumns = new ArrayList<>();
            for (String tableName : tableNames) {
                String[] columnDefs = tableColumns.get(tableName);
                for (int i = 0; i < columnDefs.length; i += 2) {
                    projectionColumns.add(tableName + "." + columnDefs[i]);
                }
            }
        } else {
            projectionColumns = Arrays.asList(attributes.split(","));
            // 去除空格
            for (int i = 0; i < projectionColumns.size(); i++) {
                projectionColumns.set(i, projectionColumns.get(i).trim());
            }
        }

        // 执行投影操作
        displayQueryResult(resultData, projectionColumns, String.join(",", tableNames));
    }

    /**
     * 计算多个表的笛卡尔积
     *
     * @param tableDataList 各表的数据列表
     * @param tableNames    表名列表
     * @return 笛卡尔积结果
     */
    private List<Map<String, Object>> computeCartesianProduct(List<List<Map<String, Object>>> tableDataList, String[] tableNames) {
        List<Map<String, Object>> result = new ArrayList<>();

        // 递归计算笛卡尔积
        computeCartesianProductRecursive(tableDataList, tableNames, 0, new HashMap<>(), result);

        return result;
    }

    /**
     * 递归计算笛卡尔积
     *
     * @param tableDataList 各表的数据列表
     * @param tableNames    表名列表
     * @param index         当前处理的表索引
     * @param currentRow    当前正在构建的行
     * @param result        结果列表
     */
    private void computeCartesianProductRecursive(List<List<Map<String, Object>>> tableDataList,
                                                  String[] tableNames,
                                                  int index,
                                                  Map<String, Object> currentRow,
                                                  List<Map<String, Object>> result) {
        // 基本情况：已处理完所有表
        if (index == tableDataList.size()) {
            result.add(new HashMap<>(currentRow));
            return;
        }

        // 获取当前表的数据
        List<Map<String, Object>> currentTableData = tableDataList.get(index);
        String currentTableName = tableNames[index];

        // 遍历当前表的每一行
        for (Map<String, Object> row : currentTableData) {
            // 创建新的行副本
            Map<String, Object> newRow = new HashMap<>(currentRow);

            // 将当前行的字段添加到新行中（带表名前缀）
            for (Map.Entry<String, Object> entry : row.entrySet()) {
                newRow.put(currentTableName + "." + entry.getKey(), entry.getValue());
            }

            // 递归处理下一个表
            computeCartesianProductRecursive(tableDataList, tableNames, index + 1, newRow, result);
        }
    }

    /**
     * 筛选满足条件的行（单表）
     *
     * @param tableData  表数据
     * @param conditions 条件表达式
     * @param tableName  表名
     * @return 满足条件的行
     */
    private List<Map<String, Object>> filterRows(List<Map<String, Object>> tableData, String conditions, String tableName) {
        List<Map<String, Object>> result = new ArrayList<>();

        // 解析条件表达式（支持 AND 连接的多个条件）
        String[] conditionParts = conditions.split(" AND ");

        for (Map<String, Object> row : tableData) {
            boolean match = true;

            // 检查每个条件
            for (String condition : conditionParts) {
                condition = condition.trim();

                // 匹配条件格式：属性名 操作符 值
                Pattern condPattern = Pattern.compile("(\\w+)\\s*(=|<|>)\\s*(.+)");
                Matcher condMatcher = condPattern.matcher(condition);

                if (condMatcher.find()) {
                    String attrName = condMatcher.group(1);
                    String operator = condMatcher.group(2);
                    String valueStr = condMatcher.group(3).trim();

                    // 处理字符串值（去除引号）
                    if (valueStr.startsWith("'") && valueStr.endsWith("'")) {
                        valueStr = valueStr.substring(1, valueStr.length() - 1);
                    }

                    // 获取行中对应属性的值
                    Object rowValue = row.get(attrName);

                    if (rowValue == null) {
                        match = false;
                        break;
                    }

                    // 根据操作符比较值
                    if (!compareValues(rowValue, operator, valueStr)) {
                        match = false;
                        break;
                    }
                } else {
                    throw new IllegalArgumentException("Invalid condition: " + condition);
                }
            }

            if (match) {
                result.add(row);
            }
        }

        return result;
    }

    /**
     * 筛选满足条件的行（多表连接）
     *
     * @param tableData    连接后的数据
     * @param conditions   条件表达式
     * @param tableNames   表名列表
     * @param tableColumns 各表的列定义
     * @return 满足条件的行
     */
    private List<Map<String, Object>> filterJoinedRows(List<Map<String, Object>> tableData,
                                                       String conditions,
                                                       String[] tableNames,
                                                       Map<String, String[]> tableColumns) {
        List<Map<String, Object>> result = new ArrayList<>();

        // 解析条件表达式（支持 AND 连接的多个条件）
        String[] conditionParts = conditions.split(" AND ");

        for (Map<String, Object> row : tableData) {
            boolean match = true;

            // 检查每个条件
            for (String condition : conditionParts) {
                condition = condition.trim();

                // 匹配条件格式：属性名 操作符 值（值可能是另一个属性名）
                Pattern condPattern = Pattern.compile("([\\w.]+)\\s*(=|<|>)\\s*([\\w.']+)");
                Matcher condMatcher = condPattern.matcher(condition);

                if (condMatcher.find()) {  // 若条件格式匹配成功
                    String leftAttr = condMatcher.group(1);  // 左侧属性（如"student.id"）
                    String operator = condMatcher.group(2);  // 运算符（如"="）
                    String rightValue = condMatcher.group(3).trim();  // 右侧值（如"score.stu_id"，去除空格）

                    // 获取左值
                    Object leftValue = row.get(leftAttr);
                    if (leftValue == null) {
                        match = false;
                        break;
                    }

                    Object rightValueObj;
                    // 判断右值是属性名还是常量
                    if (rightValue.startsWith("'") && rightValue.endsWith("'")) {
                        // 字符串常量
                        rightValueObj = rightValue.substring(1, rightValue.length() - 1);
                    } else if (row.containsKey(rightValue)) {
                        // 另一个属性
                        rightValueObj = row.get(rightValue);
                    } else {
                        // 数字常量或其他
                        try {
                            rightValueObj = Integer.parseInt(rightValue);
                        } catch (NumberFormatException e) {
                            rightValueObj = rightValue;
                        }
                    }

                    // 根据操作符比较值
                    if (!compareValues(leftValue, operator, rightValueObj)) {
                        match = false;
                        break;
                    }
                } else {
                    throw new IllegalArgumentException("Invalid condition: " + condition);
                }
            }

            if (match) {
                result.add(row);
            }
        }

        return result;
    }

    /**
     * 比较两个值
     *
     * @param leftValue  左值
     * @param operator   操作符
     * @param rightValue 右值
     * @return 比较结果
     */
    private boolean compareValues(Object leftValue, String operator, Object rightValue) {
        // 如果右值是字符串形式的数字，尝试转换为数字
        if (rightValue instanceof String) {
            String rightStr = (String) rightValue;
            try {
                rightValue = Integer.parseInt(rightStr);
            } catch (NumberFormatException e) {
                // 保持为字符串
            }
        }

        // 类型匹配检查
        if (leftValue instanceof Integer && rightValue instanceof Integer) {
            int leftInt = (Integer) leftValue;
            int rightInt = (Integer) rightValue;

            return switch (operator) {
                case "=" -> leftInt == rightInt;
                case "<" -> leftInt < rightInt;
                case ">" -> leftInt > rightInt;
                default -> throw new IllegalArgumentException("Unsupported operator: " + operator);
            };
        } else {
            String leftStr = leftValue.toString();
            String rightStr = rightValue.toString();

            return switch (operator) {
                case "=" -> leftStr.equals(rightStr);
                case "<" -> leftStr.compareTo(rightStr) < 0;
                case ">" -> leftStr.compareTo(rightStr) > 0;
                default -> throw new IllegalArgumentException("Unsupported operator: " + operator);
            };
        }
    }

    /**
     * 显示查询结果
     *
     * @param resultData        结果数据
     * @param projectionColumns 投影列
     * @param tableInfo         表信息（用于显示）
     */
    private void displayQueryResult(List<Map<String, Object>> resultData, List<String> projectionColumns, String tableInfo) {
        // 显示表头
        System.out.println("=== Query Result ===");
        System.out.println(String.join(", ", projectionColumns));

        // 显示数据行
        for (Map<String, Object> row : resultData) {
            List<String> values = new ArrayList<>();
            for (String column : projectionColumns) {
                Object value = row.get(column);
                if (value == null) {
                    values.add("NULL");
                } else {
                    values.add(value.toString());
                }
            }
            System.out.println(String.join(", ", values));
        }

        System.out.println("Total rows: " + resultData.size());
    }

    // ======================== 核心SQL操作实现 ========================

    /**
     * 处理CREATE TABLE命令：创建新表并定义结构
     * 语法示例：CREATE TABLE student (id INT, name STRING, age INT);
     * 【修复点2】修复元数据末尾多逗号问题，避免解析时数组长度异常
     */
    private void createTable(String sql) {
        // 分组说明：group1=表名，group2=列定义字符串（如"id INT, name STRING"）
        Pattern pattern = Pattern.compile(
                "CREATE TABLE (\\w+) \\((.+?)\\)",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            String tableName = matcher.group(1);       // 提取表名（如"student"）
            String columnsDef = matcher.group(2);      // 提取列定义（如"id INT, name STRING"）

            // 语义检查：表是否已存在（避免重复创建）
            if (metadata.containsKey(tableName)) {
                throw new IllegalArgumentException("Table already exists: " + tableName);
            }

            // 拆分列定义：按逗号分割为单个列的定义（如["id INT", " name STRING"]）
            String[] columns = columnsDef.split(",");
            // 构建元数据字符串（格式："列名1,类型1,列名2,类型2"）
            StringBuilder metaBuilder = new StringBuilder();

            for (int i = 0; i < columns.length; i++) {
                String col = columns[i].trim();  // 去除列定义的前后空格（如" name STRING"→"name STRING"）
                // 按空格分割列名和类型（支持多个空格，如"id   INT"→["id", "INT"]）
                String[] parts = col.split("\\s+");

                // 语义检查：列定义是否合法（必须包含列名和类型，如"id INT"是合法的）
                if (parts.length < 2) {
                    throw new IllegalArgumentException("Invalid column definition: " + col);
                }

                metaBuilder.append(parts[0]).append(",").append(parts[1]);
                // 仅在非最后一列后添加逗号（避免末尾多逗号）
                if (i != columns.length - 1) {
                    metaBuilder.append(",");
                }
            }

            // 将表结构存入元数据（内存）
            metadata.setProperty(tableName, metaBuilder.toString());
            // 初始化表的数据存储（内存中创建空列表）
            storage.put(tableName, new ArrayList<>());
            // 保存元数据到磁盘（持久化表结构）
            saveMetadata();

            System.out.println("Table created: " + tableName);
        } else {
            // 正则匹配失败→语法错误（如缺少括号、表名格式错误等）
            throw new IllegalArgumentException("Invalid CREATE TABLE syntax");
        }
    }

    /**
     * 处理INSERT INTO命令：向表中插入一条记录
     * 语法示例：INSERT INTO student (id, name, age) VALUES (1, '张三', 20);
     */
    private void insertData(String sql) {
        // 正则表达式：匹配表名、列名列表、值列表
        Pattern pattern = Pattern.compile(
                "INSERT INTO (\\w+)\\s*\\(([^)]+)\\)\\s*VALUES\\s*\\(([^)]+)\\)",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            String tableName = matcher.group(1);       // 表名
            String[] columns = matcher.group(2).split(",");  // 列名列表（如["id", "name", "age"]）
            String[] values = matcher.group(3).split(",");   // 值列表（如["1", "'张三'", "20"]）

            // 语义检查：表是否存在
            if (!metadata.containsKey(tableName)) {
                throw new IllegalArgumentException("Table not exists: " + tableName);
            }

            // 获取表的列定义（从元数据解析）
            String[] columnDefs = metadata.getProperty(tableName).split(",");
            int expectedColCount = columnDefs.length / 2;  // 预期的列数（元数据长度/2）
            // 语义检查：插入的列数是否与表的列数一致
            if (columns.length != expectedColCount) {
                throw new IllegalArgumentException("Column count mismatch: expected " + expectedColCount + ", got " + columns.length);
            }

            // 存储当前行数据的Map
            Map<String, Object> row = new HashMap<>();
            // 遍历列名和值，匹配并转换类型
            for (int i = 0; i < columns.length; i++) {
                String colName = columns[i].trim();    // 列名（去除空格）
                String colType = columnDefs[i * 2 + 1].trim();  // 列类型（如"INT"）
                // 处理值：去除空格和首尾单引号（如"'张三'"→"张三"）
                String val = values[i].trim().replaceAll("^'|'$", "");

                // 转换值为对应类型并存入Map
                row.put(colName, convertValue(val, colType));
            }

            // 将行数据添加到内存存储
            storage.get(tableName).add(row);
            // 保存数据到磁盘（持久化）
            saveStorage();
            System.out.println("Data inserted into " + tableName);
        } else {
            throw new IllegalArgumentException("Invalid INSERT syntax");
        }
    }

    /**
     * 处理ALTER TABLE命令：为表添加新列（仅支持添加列操作）
     * 语法示例：ALTER TABLE student ADD gender STRING;
     */
    private void alterTable(String sql) {
        // 正则表达式：匹配表名、新列名、新列类型
        Pattern pattern = Pattern.compile(
                "ALTER TABLE (\\w+) ADD (\\w+) (\\w+)",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            String tableName = matcher.group(1);   // 表名
            String colName = matcher.group(2);     // 新列名
            String colType = matcher.group(3);     // 新列类型

            // 语义检查：表是否存在
            if (!metadata.containsKey(tableName)) {
                throw new IllegalArgumentException("Table not exists: " + tableName);
            }

            // 更新元数据：在原有结构后追加新列的"列名,类型"
            String oldMeta = metadata.getProperty(tableName);
            String newMeta = oldMeta + "," + colName + "," + colType;  // 拼接新列定义
            metadata.setProperty(tableName, newMeta);
            saveMetadata();  // 保存更新后的表结构

            // 为现有数据添加新列的默认值
            List<Map<String, Object>> tableData = storage.get(tableName);
            for (Map<String, Object> row : tableData) {
                row.put(colName, "DEFAULT");  // 默认值为"DEFAULT"
            }

            // 保存更新后的数据
            saveStorage();
            System.out.println("Column added to " + tableName);
        } else {
            throw new IllegalArgumentException("Invalid ALTER TABLE syntax");
        }
    }

    /**
     * 处理DELETE FROM命令：删除表中符合条件的记录（支持WHERE子句或删除所有）
     * 语法示例：DELETE FROM student WHERE age < 20;（带条件）或DELETE FROM student;（删除所有）
     */
    private void deleteData(String sql) {
        // 正则表达式：匹配表名和可选的WHERE条件
        Pattern pattern = Pattern.compile(
                "DELETE FROM (\\w+)( WHERE (.+))?",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            String tableName = matcher.group(1);   // 表名
            String condition = matcher.group(3);   // WHERE条件（null表示删除所有）

            // 语义检查：表是否存在
            if (!metadata.containsKey(tableName)) {
                throw new IllegalArgumentException("Table not exists: " + tableName);
            }

            List<Map<String, Object>> tableData = storage.get(tableName);
            // 情况1：无WHERE条件→删除所有记录
            if (condition == null) {
                tableData.clear();  // 清空列表
            }
            // 情况2：有WHERE条件→删除符合条件的记录
            else {
                // 子正则：匹配条件（仅支持单个条件，如id=1、age<20、name='张三'）
                Pattern condPattern = Pattern.compile(
                        "(\\w+)\\s*(=|<|>)\\s*(\\w+)",
                        Pattern.CASE_INSENSITIVE
                );
                Matcher condMatcher = condPattern.matcher(condition);

                if (!condMatcher.find()) {
                    throw new IllegalArgumentException("Invalid condition: " + condition);
                }

                String colName = condMatcher.group(1);     // 条件列名（如"age"）
                String operator = condMatcher.group(2);   // 运算符（如"<"）
                String condVal = condMatcher.group(3).replaceAll("^'|'$", "");  // 条件值（如"20"）

                // 存储未被删除的记录（避免边遍历边删除导致异常）
                List<Map<String, Object>> newData = new ArrayList<>();
                for (Map<String, Object> row : tableData) {
                    Object rowVal = row.get(colName);  // 当前行的条件列值
                    boolean match = false;  // 是否匹配条件（匹配则删除）

                    // 分类型比较（INT和String的比较逻辑不同）
                    if (rowVal instanceof Integer) {
                        // INT类型：转换为数字后比较
                        int rowInt = (Integer) rowVal;
                        int condInt = Integer.parseInt(condVal);
                        switch (operator) {
                            case "=":
                                match = (rowInt == condInt);
                                break;
                            case "<":
                                match = (rowInt < condInt);
                                break;
                            case ">":
                                match = (rowInt > condInt);
                                break;
                        }
                    } else {
                        // String类型：直接按字符串比较（字典序）
                        String rowStr = (String) rowVal;
                        switch (operator) {
                            case "=":
                                match = rowStr.equals(condVal);
                                break;
                            case "<":
                                match = rowStr.compareTo(condVal) < 0;
                                break;
                            case ">":
                                match = rowStr.compareTo(condVal) > 0;
                                break;
                        }
                    }

                    // 不匹配条件→保留该行
                    if (!match) {
                        newData.add(row);
                    }
                }
                // 用新列表替换原数据（完成删除操作）
                storage.put(tableName, newData);
            }

            // 保存删除后的结果
            saveStorage();
            System.out.println("Data deleted from " + tableName);
        } else {
            throw new IllegalArgumentException("Invalid DELETE syntax");
        }
    }

    /**
     * 处理UPDATE命令：更新表中符合条件的记录（支持WHERE子句或更新所有）
     * 语法示例：UPDATE student SET age=19 WHERE id=2;（带条件）或UPDATE student SET age=19;（更新所有）
     */
    private void updateData(String sql) {
        // 正则表达式：匹配表名、修改列、新值、可选的WHERE条件
        Pattern pattern = Pattern.compile(
                "UPDATE (\\w+) SET (\\w+)=(\\w+)( WHERE (.+))?",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            String tableName = matcher.group(1);   // 表名
            String colName = matcher.group(2);     // 要修改的列名
            // 新值：去除首尾单引号（如"'男'"→"男"）
            String newValue = matcher.group(3).replaceAll("^'|'$", "");
            String condition = matcher.group(5);   // WHERE条件（null表示更新所有）

            // 语义检查：表是否存在
            if (!metadata.containsKey(tableName)) {
                throw new IllegalArgumentException("Table not exists: " + tableName);
            }

            // 语义检查：修改的列是否存在
            String[] columnDefs = metadata.getProperty(tableName).split(",");
            boolean colExists = false;
            String colType = "";  // 记录列类型，用于转换新值
            for (int i = 0; i < columnDefs.length; i += 2) {
                if (columnDefs[i].equals(colName)) {
                    colExists = true;
                    colType = columnDefs[i + 1];  // 获取列类型
                    break;
                }
            }
            if (!colExists) {
                throw new IllegalArgumentException("Column not exists: " + colName);
            }

            // 转换新值为列定义的类型（确保类型一致，如INT列不能赋值字符串）
            Object convertedValue = convertValue(newValue, colType);

            List<Map<String, Object>> tableData = storage.get(tableName);
            // 情况1：无WHERE条件→更新所有记录
            if (condition == null) {
                for (Map<String, Object> row : tableData) {
                    row.put(colName, convertedValue);
                }
            }
            // 情况2：有WHERE条件→更新符合条件的记录
            else {
                // 解析条件（同DELETE的条件解析逻辑）
                Pattern condPattern = Pattern.compile(
                        "(\\w+)\\s*(=|<|>)\\s*(\\w+)",
                        Pattern.CASE_INSENSITIVE
                );
                Matcher condMatcher = condPattern.matcher(condition);

                if (!condMatcher.find()) {
                    throw new IllegalArgumentException("Invalid condition: " + condition);
                }

                String condCol = condMatcher.group(1);    // 条件列名
                String operator = condMatcher.group(2);   // 运算符
                String condVal = condMatcher.group(3).replaceAll("^'|'$", "");  // 条件值

                // 遍历所有行，更新符合条件的记录
                for (Map<String, Object> row : tableData) {
                    Object rowVal = row.get(condCol);  // 当前行的条件列值
                    boolean match = false;  // 是否匹配条件（匹配则更新）

                    // 分类型比较条件
                    if (rowVal instanceof Integer) {
                        int rowInt = (Integer) rowVal;
                        int condInt = Integer.parseInt(condVal);
                        match = switch (operator) {
                            case "=" -> (rowInt == condInt);
                            case "<" -> (rowInt < condInt);
                            case ">" -> (rowInt > condInt);
                            default -> false;
                        };
                    } else {
                        String rowStr = (String) rowVal;
                        match = switch (operator) {
                            case "=" -> rowStr.equals(condVal);
                            case "<" -> rowStr.compareTo(condVal) < 0;
                            case ">" -> rowStr.compareTo(condVal) > 0;
                            default -> false;
                        };
                    }

                    // 匹配条件→更新该列的值
                    if (match) {
                        row.put(colName, convertedValue);
                    }
                }
            }

            // 保存更新后的结果
            saveStorage();
            System.out.println("Data updated in " + tableName);
        } else {
            throw new IllegalArgumentException("Invalid UPDATE syntax");
        }
    }

    /**
     * 处理DROP TABLE命令：删除表（包括结构和数据）
     * 语法示例：DROP TABLE student;
     */
    private void dropTable(String sql) {
        // 正则表达式：匹配表名
        Pattern pattern = Pattern.compile(
                "DROP TABLE (\\w+)",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            String tableName = matcher.group(1);   // 表名

            // 语义检查：表是否存在
            if (!metadata.containsKey(tableName)) {
                throw new IllegalArgumentException("Table not exists: " + tableName);
            }

            // 1.从元数据中删除表（移除结构）
            metadata.remove(tableName);
            // 2.从内存中删除表数据
            storage.remove(tableName);
            // 3.删除磁盘上的数据文件（data/表名.dat）
            new File(DATA_DIR, tableName + ".dat").delete();

            System.out.println("Table dropped: " + tableName);
        } else {
            throw new IllegalArgumentException("Invalid DROP TABLE syntax");
        }
    }

    /**
     * 处理SELECT * FROM命令：显示表的结构和所有数据
     * 语法示例：SELECT * FROM student;
     */
    private void displayTable(String sql) {
        // 正则表达式：匹配表名
        Pattern pattern = Pattern.compile(
                "SELECT \\* FROM (\\w+)",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(sql);

        if (matcher.find()) {
            String tableName = matcher.group(1);   // 表名

            // 语义检查：表是否存在
            if (!metadata.containsKey(tableName)) {
                throw new IllegalArgumentException("Table not exists: " + tableName);
            }

            // 1.显示表结构（列名+类型）
            System.out.println("=== Structure ===");
            String[] columns = metadata.getProperty(tableName).split(",");
            // 遍历列定义，每次取"列名+类型"（i+=2）
            for (int i = 0; i < columns.length; i += 2) {
                System.out.println(columns[i] + " (" + columns[i + 1] + ")");
            }

            // 2.显示表数据
            System.out.println("\n=== Data ===");
            List<Map<String, Object>> tableData = storage.get(tableName);
            // 若表中无数据，提示"无数据"
            if (tableData.isEmpty()) {
                System.out.println("No data in table.");
                return;
            }

            // 遍历所有行，按列顺序打印字段值
            for (Map<String, Object> row : tableData) {
                List<String> values = new ArrayList<>();
                for (int i = 0; i < columns.length; i += 2) {
                    // 按列名获取值并转为字符串
                    values.add(row.get(columns[i]).toString());
                }
                // 用逗号+空格拼接值，打印一行数据（如"1, 张三, 20"）
                System.out.println(String.join(", ", values));
            }
        } else {
            throw new IllegalArgumentException("Invalid SELECT syntax");
        }
    }
}